package com.j.lemon.learn.thread.lock;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * @Author lijunjun
 * @Date 2019-04-18 10:31
 * @Description 读写锁
 *
 *
 * 独占锁：指该锁一次只能被一个线程锁持有，Reentrantlock和Synchronized都是独占锁
 * 共享锁：指该锁可被多个线程所持有
 *
 * 读写锁的，读锁是共享锁，写锁是独占锁
 *
 * 读写锁ReentrantReadWritelock，读的时候，加锁不阻塞，写的时候，加锁阻塞， 如果只在写入加锁，读取部分没加锁，一样会出现线程不安全问题，A线程还没写完，B就读了
 *
 * 读写锁的  读取的时候，其他线程不能写，但是可以读取
 *          写的时候，其他线程不能写，也不能读
 */
public class ReadWriteLockDemo {
    public static void main(String[] args) {
        MyCache myCache = new MyCache();


        for (int i = 1; i < 6; i++) {
            final int temp = i;
            new Thread(()->{
                myCache.put(temp+"",temp+"");
            },String.valueOf(i)).start();
        }

        for (int i = 1; i < 6; i++) {
            final int temp = i;
            new Thread(()->{
                myCache.get(temp+"");
            },String.valueOf(i)).start();
        }
    }
}


class MyCache{
    private volatile Map<String,Object> map = new HashMap<>();
    ReentrantReadWriteLock wrlock = new ReentrantReadWriteLock();

//    private ConcurrentHashMap<String,Object> map = new ConcurrentHashMap<>();

    public void put(String k,Object v){
        wrlock.writeLock().lock();
        try{
            System.out.println(Thread.currentThread().getName() + "正在写入：" + k);
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            map.put(k,v);
            System.out.println(Thread.currentThread().getName() + "写入完成：" + k);
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            wrlock.writeLock().unlock();
        }
    }

    public void get(String k){
        wrlock.readLock().lock();
        try{
            System.out.println(Thread.currentThread().getName() + "正在读取：" + k);
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            Object o = map.get(k);
            System.out.println(Thread.currentThread().getName() + "读取完成：" + o);
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            wrlock.readLock().unlock();
        }
    }
}
